home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Tele / C / Comet2.1.3 Folder / Comet / screen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-04  |  40.3 KB  |  1,923 lines  |  [TEXT/dumv]

  1. /*
  2.     Copyright Cornell University 1986.  All rights are reserved.
  3.  
  4.     screenpaint.c contains routines using both direct-to-screen
  5.     bit-painting (ds) routines defined in emlib and QuickDraw calls to draw
  6.     the screen.  Each basic call comes in two flavors to support 
  7.     either the ds or qd drawing mode; the application uses routine vectors
  8.     which are reset so that the correct mode
  9.     is automatically used.
  10.     
  11.     updatewind is the screen update call.
  12.  
  13. */
  14.  
  15. #include     <em.h>
  16.  
  17. #include    <3270.h>
  18. #include    <rcodes.h>
  19. #include    <h19.h>
  20. #include    "menudefs.h"
  21.  
  22.  
  23. #define ATUNPROT    0
  24. #define ATPROT        8
  25.  
  26. #define ATNORM        0
  27. #define ATSENSE        2
  28. #define ATINTENSE    4
  29. #define ATINVIS        6
  30.  
  31. #define ATFORE        0
  32. #define ATBACK        1
  33.  
  34.  
  35.  
  36. char * blankstart = 
  37. "                                                                               \
  38.                                                                                ";
  39. /* > 132 blanks */
  40.  
  41. short inscreen_service;            /* don't allow reentrant calls-might work, but... */
  42.  
  43. /* go through the array of connections and update any that need screen updates */
  44.  
  45. screen_service()
  46. {
  47.     struct winds ** conp = conns;
  48.     struct winds * conend = &conp[conncount];
  49.     register struct winds * twp;
  50.     short cursortime;
  51.     short giveupdate;
  52.     GrafPtr oport;
  53.     GrafPtr frontwind = FrontWindow();
  54.     
  55.     if (inemulator || mfbackonly)
  56.         return(-1);
  57.         
  58.     if (inscreen_service)
  59.         return;
  60.     inscreen_service = TRUE;
  61.     
  62.     giveupdate = cupdatewait(keydp);
  63.     if (cticks > tickcursor) {
  64.         /* do this stuff but 60 times/second */
  65.         maccursor(giveupdate);            
  66.             /* change/track cursor in key emwindow; leaves port set to keydp->emwindow */
  67.         tickcursor = cticks + 1;
  68.     }
  69. #ifdef NUTS
  70.     /* hey, this is stupid!  */
  71.     if (giveupdate) {
  72.         /* no drawing should be done anyway */
  73.         inscreen_service = FALSE;
  74.         return(-1);
  75.     }
  76. #endif
  77.  
  78.     if (cticks > cursalarm)  {
  79.         setcursalarm();
  80.         cursortime = TRUE;
  81.     }
  82.     else
  83.         cursortime = FALSE;
  84.  
  85.     /* go through window list to see who needs service */
  86.     for ( ; conp < conend ; ) {
  87.         twp = *conp++;
  88.         if (twp == NULL)
  89.             continue;
  90.             
  91.         if (twp->emwindow == NULL)
  92.             /* has no window to update... */
  93.             continue;
  94.             
  95.         if (cursortime || twp->cursorwait) {
  96.             if (twp->curson == FALSE) {
  97.                 /* make sure the cursor gets turned on */
  98.                 getcontext(twp);
  99.                 cursorblink();
  100.             }
  101.             else if (twp->emwindow == frontwind && !mfbackground) {
  102.                 /* make sure the cursor blinks if front window */
  103.                 getcontext(twp);
  104.                 cursorblink();
  105.             }
  106.             if (twp->textwindow == frontwind && !mfbackground) {
  107.                 GetPort(&oport);
  108.                 SetPort(twp->textwindow);
  109.                 TEIdle(twp->texthand);
  110.                 SetPort(oport);
  111.             }
  112.         }
  113.         
  114. #ifdef MACTCP
  115.         if (cticks > tickstats) {
  116.             if (twp->conntype == CONN_MACTCP) {
  117.                 tcp_drawcount(twp);
  118.             }
  119.         }
  120. #endif
  121. #ifdef DUALTCP
  122.         if (cticks > tickstats) {
  123.             if (twp->conntype == CONN_MACTCP) {
  124.                 tcp_drawcount(twp);
  125.             }
  126.             if (twp->conntype == CONN_CUTCP) {
  127.                 extern unsigned long ipsnd;
  128.                 extern unsigned long iprcv;
  129.                 
  130.                 if (twp->in_cnt != iprcv) {
  131.                     twp->in_cnt = iprcv;
  132.                     getcontext(twp);
  133.                     drawincount();
  134.                 }
  135.                 if (twp->out_cnt != ipsnd) {
  136.                     twp->out_cnt = ipsnd;
  137.                     getcontext(twp);
  138.                     drawoutcount();
  139.                 }
  140.             }
  141.         }
  142. #endif
  143.         if (!twp->modflg)
  144.             /* no need for updates*/
  145.             continue;
  146.             
  147.         /* reset output context */
  148.         getcontext(twp);
  149.         
  150.         if (twp->ibm_mode) {
  151.             if (twp->event_reg & SCREEN_EVENT) {
  152.                 /* update the 3270 screen if EOR has been received */
  153.                 (*twp->screen_upd)();
  154.                 twp->modflg = modflg;
  155.                 twp->clrflg = clrflg;
  156.                     /* update modflg which may have changed */
  157. #ifdef DUALTCP
  158.                 if (twp->conntype == CONN_CUTCP)
  159.                     /* Cornell tcp needs frequent attention */
  160.                     datayield();
  161. #endif
  162.             }
  163.             continue;
  164.         }
  165.         else {
  166.             if (twp->modflg) {
  167.                 (*twp->screen_upd)();
  168.                 twp->modflg = modflg;
  169.                 twp->clrflg = clrflg;
  170. #ifdef DUALTCP
  171.                 if (twp->conntype == CONN_CUTCP)
  172.                     datayield();
  173. #endif
  174.             }
  175.             continue;
  176.         }
  177.     }        /* end of loop through window structure array */
  178.  
  179.     /* update tick counters if necessary */
  180.     if (cticks > tickstats)
  181.         tickstats = cticks + 60;
  182.  
  183.     inscreen_service = FALSE;
  184. }
  185.  
  186.  
  187. /* respond to a window update event; the grafport is already set */
  188.  
  189. updatewind_qd() 
  190. {
  191.     int oldfont;
  192.     long omodflg;
  193.     short color = emdp->color;
  194.     GrafPtr oldport;
  195.     int oldsize;
  196.     
  197.     if (emdp->backonly)
  198.         return;
  199.  
  200.     oldfont = emwindow->txFont;
  201.     oldsize = emwindow->txSize;
  202.  
  203.     GetPort(&oldport);
  204.     SetPort(emwindow);
  205.  
  206.     TextSize(emdp->fontsize);
  207.     
  208.     omodflg = modflg;                /* save; otherwise lines outside update rgn not redrawn */
  209.     modflg = (long) SCRALLMOD;        /* set line-changed map to all TRUE */
  210.  
  211.     /* blank out cursors before drawing:  invert whole rect 
  212.         before setting cliprgn w/ beginupdate() */
  213.     if (emdp == keydp && trackon) {
  214.         InvertRect(&mouserect);
  215.     }
  216.     if (emdp->curson) {
  217.         InvertRect(&emdp->cursrect);
  218.     }
  219.  
  220.     emdp->mfwait = FALSE;
  221.  
  222.     BeginUpdate(emwindow);
  223.  
  224.     /* now when we invert again any portion in the update region will be inverted
  225.         to blank... */
  226.     if (emdp == keydp && trackon) {
  227.         InvertRect(&mouserect);
  228.         trackon = FALSE;
  229.     }
  230.     if (emdp->curson) {
  231.         InvertRect(&emdp->cursrect);
  232.         emdp->curson = FALSE;
  233.     }
  234.  
  235.     prettywind(TRUE);
  236.  
  237.     if (line25on(emdp)) {
  238.         line25refresh();
  239.     }
  240.     else {
  241.         if (emdp->termset) {
  242.             /* don't draw controls until there's a terminal selected */
  243.             if (emdp->controlschanged || !emdp->dsdraw) {
  244.                 drawq1controls();
  245.                 copytoprect(emwindow);            /* copy the control pics to reuse */
  246.             }
  247.             else
  248.                 pastetoprect(emwindow);
  249.         }
  250.     }
  251.     drawversion("");
  252.     drawincount();
  253.     drawoutcount();
  254.  
  255.     oldfont = emwindow->txFont;
  256.  
  257.     if (emdp->selrectvis && !color) {
  258.         /* if user has selected some text, invert it again within update clip */
  259.         selinvert(emdp);
  260.     }
  261.     if (!emdp->emdisable) {
  262.         /* update the emulator contents */
  263.         if (emdp->ibm_mode)
  264.             ibmpaintbuf(scr_map, color ? FALSE : TRUE);
  265.         else
  266.             paintbuf(&emdp->charr[0], color ? FALSE : TRUE);
  267.     }
  268.     if (emdp->selrectvis && color) {
  269.         /* must be inverted promptly within update clip */
  270.         selinvert(emdp);
  271.     }
  272.     TextFont(oldfont);
  273.     if (color) {
  274.         BackColor((long) whiteColor);
  275.         ForeColor((long) blackColor);
  276.     }
  277.     if (emdp->ibm_keymode) {
  278.         arcrefresh();                    /* 3270ft bytes-transferred drawing */
  279.     }
  280.     if (emdp->ibm_mode) {
  281.         status_info();
  282.     }
  283.     modflg = omodflg;                /* restore modflg */
  284.  
  285.     EndUpdate(emwindow);            /* end the update */
  286.  
  287.     InvertRect(&emdp->cursrect);    /* turn the cursor on */
  288.     emdp->curson = TRUE;
  289.     setcursalarm();
  290.     SetPort(oldport);
  291. }
  292.  
  293.  
  294. /*    
  295.  *    write count bytes from srcptr to linear screen position dest;
  296.  *    do not move cursor
  297.  */
  298.  
  299. str_draw_qd(srcptr, count, attr)
  300. unsigned char * srcptr;
  301. register int count;
  302. unsigned char attr;
  303. {
  304.     unsigned char thechar;
  305.     int savex, savey;
  306.     int oldfont;
  307.     char invisible;
  308.  
  309.     if (updatewait()) {
  310.         /* delay drawing */
  311.         modflg |= SCRALLMOD;            /* for convenience we redraw the whole thing */
  312.         emdp->event_reg |= SCREEN_EVENT;
  313.         return;
  314.     }        
  315.  
  316.     savex = xpos;
  317.     savey = ypos;
  318.  
  319.     ypos = (srcptr - scr_map) / emdp->linelength;
  320.     xpos = (srcptr - scr_map) - (ypos * emdp->linelength);
  321.  
  322.     oldfont = emwindow->txFont;
  323.  
  324.     invisible = setscreenattr_qd(attr);
  325.     
  326.     prepibmdraw_qd();
  327.     count++;                                /* set up for predecrement  */
  328.     clrflg &= ~modmask[ypos];                /* reset clear flag */
  329.     
  330.     while (--count > 0) 
  331.     {
  332.         if (invisible) {
  333.             /* blank the character */
  334.             thechar = ' ';
  335.             srcptr++;
  336.         }
  337.         else {
  338.             thechar = *srcptr++;
  339.         }
  340.         ibmpaintchar(thechar);
  341.         if (++xpos >= emdp->linelength) {
  342.             xpos = 0;
  343.             clrflg &= ~modmask[ypos];        /* reset clear flag */
  344.             if (++ypos >= emdp->linecount)
  345.                 ypos = 0;
  346.         }
  347.     }
  348.  
  349.     /* restore the old x, y values and the old cursor */
  350.     xpos = savex;
  351.     ypos = savey;
  352.     endibmdraw_qd();
  353.     TextFont(oldfont);
  354.     if (emdp->color) {
  355.         BackColor((long) whiteColor);
  356.         ForeColor((long) blackColor);
  357.     }
  358. }
  359.  
  360.  
  361. /* draw a character on the screen; fix cursor later after cursor_ptr update */
  362.  
  363. ibmch_draw_qd(thechar, attr)
  364. unsigned char thechar; 
  365. unsigned char attr;
  366. {
  367.     int oldfont;
  368.     int oldsize;
  369.  
  370.     if (updatewait()) {
  371.         /* delay drawing */
  372.         set_mod(cursor_ptr, 1);
  373.         emdp->event_reg |= SCREEN_EVENT;
  374.         return;
  375.     }        
  376.  
  377.     oldfont = emwindow->txFont;
  378.     oldsize = emwindow->txSize;
  379.  
  380.     if (setscreenattr_qd(attr))
  381.         /* invis, blank the character */
  382.         thechar = ' ';
  383.  
  384.     prepibmdraw_qd();
  385.  
  386.     /* do it */
  387.     ibmpaintchar(thechar);
  388.     clrflg &= ~modmask[ypos];        /* reset clear flag */
  389.  
  390.     endibmdraw_qd();
  391.  
  392.     TextFont(oldfont);
  393.     TextSize(oldsize);
  394.     if (emdp->color) {
  395.         BackColor((long) whiteColor);
  396.         ForeColor((long) blackColor);
  397.     }
  398. }
  399.  
  400.  
  401. /* called to update chars on screen after host has modified */
  402.  
  403. screen_upd_qd()
  404. {
  405.     GrafPtr oldport;
  406.     int oldfont;
  407.     int oldsize;
  408.     int doinvert = TRUE;
  409.     short hadcursor;
  410.     
  411.     if (updatewait())
  412.         return;
  413.         
  414.     if (emdp->backonly)
  415.         return;
  416.  
  417.     oldfont = emwindow->txFont;
  418.     oldsize = emwindow->txSize;
  419.  
  420.     GetPort(&oldport);
  421.     SetPort(emwindow);
  422.  
  423.     TextSize(emdp->fontsize);
  424.     
  425.     if (emdp->color && emdp->selrectvis) {
  426.         /* must clear the selection and re-invert later since color QD
  427.             makes it difficult to handle this; delivers blocky 
  428.             performance */
  429.         selinvert(emdp);
  430.         doinvert = FALSE;
  431.     }
  432.     hadcursor = emdp->curson;
  433.     if (emdp->ibm_mode) {
  434.         prepibmdraw_qd();
  435.         ibmpaintbuf(scr_map, doinvert);
  436.         endibmdraw_qd();
  437.         emdp->event_reg &= ~SCREEN_EVENT;
  438.     }
  439.     else {
  440.         emprep();
  441.         paintbuf(&emdp->charr[0], doinvert);
  442.         emend();
  443.         
  444.     }
  445.     if (hadcursor) {
  446.         /* if the cursor was visible, make sure it stays that way */
  447.         InvertRect(&emdp->cursrect);    /* turn the cursor on */
  448.         emdp->curson = TRUE;
  449.         setcursalarm();
  450.     }
  451.  
  452.     if (emdp->color && emdp->selrectvis) {
  453.         /* make sure the selection rectangle gets inverted */
  454.         tm_tset(2, selrestore, emdp, emdp->sel_tm);
  455.         emdp->selrectvis = FALSE;        /* it was cleared earlier */
  456.     }
  457.         
  458.     TextFont(oldfont);
  459.     TextSize(oldsize);
  460.     if (emdp->color) {
  461.         BackColor((long) whiteColor);
  462.         ForeColor((long) blackColor);
  463.     }
  464.     SetPort(oldport);
  465. }
  466.  
  467.  
  468. /*
  469. *****  quick clear the first 24 lines off the screen
  470. */
  471.  
  472. clear_scr_qd()
  473. {
  474.     if (updatewait()) {
  475.         /* had emdp->color ||  too before EraseRect changed to clearrect */
  476.         modflg = emdp->modflg = SCRALLMOD;
  477.         emdp->event_reg |= SCREEN_EVENT;
  478.         return;
  479.     }
  480.         
  481.     if (clrflg >= SCRALLMOD)
  482.         /* screen is already clear */
  483.         return;
  484.  
  485.     emdp->bigrect.top = emdp->voffset;
  486.     clearrect(&emdp->bigrect);
  487.     if (emdp->selrectvis) {
  488.         /* if user has selected some text, we must rehighlight */
  489.         if (updatewait()) {
  490.             emdp->selrectvis = FALSE;
  491.             tm_tset(2, selrestore, emdp, emdp->sel_tm);
  492.         }
  493.         else
  494.             selinvert(emdp);
  495.     }
  496.     clrflg = SCRALLMOD;
  497.  
  498.     emdp->curson = FALSE;
  499.     if (emdp == keydp)
  500.         trackon = FALSE;
  501. }
  502.  
  503. prepibmdraw_qd()
  504. {
  505.     if (emdp->curson) {
  506.         /* if cursor visible, invert it */
  507.  
  508.         InvertRect(&emdp->cursrect);
  509.         emdp->curson = FALSE;
  510.     }
  511.     if (emdp == keydp && trackon) {
  512.         /* if mouserect visible, invert it */
  513.  
  514.         InvertRect(&mouserect);
  515.         trackon = FALSE;
  516.     }
  517. }
  518.  
  519.  
  520. endibmdraw_qd()
  521. {
  522.     showcursor();
  523. }
  524.  
  525.  
  526. ibmpaintchar(thechar)
  527. char thechar;
  528. {
  529.     Rect chinvrect;
  530.     int fixinv;
  531.  
  532.     fixinv = FALSE;
  533.     chinvrect.top = ypos * emdp->lineheight + emdp->voffset;
  534.     chinvrect.left = xpos * emdp->fontwidth + emdp->hoffset;
  535.  
  536.     MoveTo(chinvrect.left, chinvrect.top + emdp->lineheight - emdp->fontdescent);
  537.     if (fixinv = chkinvert()) {
  538.         if (!emdp->color)
  539.             TextMode(notSrcCopy);
  540.     }
  541.     DrawChar(thechar);
  542.     if (fixinv) {
  543.         if (emdp->color) {
  544.             /* invert the newly drawn character */
  545.             chinvrect.bottom = chinvrect.top + emdp->fontheight;    /* - 2 skipped by zap */
  546.             chinvrect.right = chinvrect.left + emdp->fontwidth;
  547.             
  548.             InvertRect(&chinvrect);
  549.         }
  550.         else
  551.             TextMode(srcCopy);
  552.     }
  553. }
  554.  
  555. /*    redraws the characters on the screen from a screen buffer.
  556.     Due to the line leading, window updates need to have the inversion
  557.     of the selection range done on the whole range--inverted char drawing
  558.     would leave non-inverted bit rows.
  559. */
  560.  
  561. ibmpaintbuf(scrbuf, invert)
  562. unsigned char * scrbuf;
  563. int invert;
  564. {
  565.     register unsigned char * textp; 
  566.     register unsigned char * drawstart;
  567.     register unsigned char * lineend;
  568.  
  569.     register unsigned char thechar;
  570.     register unsigned int dodraw;        /* draw triggered by entering selection range */
  571.     unsigned int invisible;        /* we're in an invisible field */
  572.     int doinvert = invert;
  573.     
  574.     /* here are some blank-skipping vars which are irrelevant when color,
  575.         since color spaces may have a different background color */
  576.     register unsigned int blanks = 0;    /* # blanks not to draw */
  577.     register unsigned int diacritics = 0;    /* # diacritics to draw spaces for */
  578.     unsigned long lineclr;
  579.     char zapped = FALSE;
  580.  
  581.     unsigned char attr;
  582.     unsigned char * attp;
  583.     int yloc;
  584.     int linecount;
  585.     unsigned long linemod;
  586.     int notstart;                /* start of selection range */
  587.     int notcount;                /* count of selection range */
  588.     unsigned char inselection = FALSE;    /* in selection range */
  589.     int textmode = srcCopy;
  590.     int drawcount;
  591.  
  592.     dodraw = FALSE;
  593.     
  594.     yloc = emdp->lineheight - emdp->fontdescent + emdp->voffset;        /* pen vert pos */
  595.     textp = scrbuf;
  596.  
  597. /* find and set current attribute */
  598.     if (*scrbuf < ATTR)
  599.         attr = *scrbuf;
  600.     else {
  601.         attp = look_attr(scrbuf, BACK);
  602.         attr = *attp;
  603.     }
  604.     invisible = setscreenattr_qd(attr);
  605.     if (invert) {
  606.         if (emdp->selrectvis) {
  607.             /* calculate character range over which we use notSrcCopy */
  608.             notstart = emdp->selystart * emdp->linelength + emdp->selxstart;
  609.             notcount = emdp->selyend * emdp->linelength + emdp->selxend - notstart;
  610.             if (notcount == 0)
  611.                 doinvert = FALSE;
  612.         }
  613.         else 
  614.             doinvert = FALSE;
  615.     }
  616.     TextMode(srcCopy);
  617.         
  618. #ifdef CLEARONALLMOD
  619.     /* alas this mode looks jerkier; it does speed things up w/ SKIPBLANKS on */
  620.     if (modflg == SCRALLMOD) {
  621.         /* screen was completely modified, clearing will speed blanks */
  622.         clear_scr_qd();
  623.     }
  624. #endif
  625.         
  626.     lineend = textp + emdp->linelength;
  627.     for (linecount = 0; linecount <= emdp->lastrow; linecount++, lineend += emdp->linelength) {
  628.  
  629.         linemod = modflg & modmask[linecount];
  630.         lineclr = clrflg & modmask[linecount];
  631.  
  632.         if (linemod) {
  633.             MoveTo(emdp->hoffset, yloc);
  634.             drawstart = textp;
  635.         }
  636.  
  637.         for ( ; textp < lineend; textp++) {
  638.             if (doinvert) {
  639.                 /* check to see if we're in the selection range */
  640.                 if (notstart-- == 0) {
  641.                     /* we just entered the range */
  642.                     dodraw = TRUE;
  643.                     inselection = TRUE;
  644.                 }
  645.                 if (notstart < 0) {
  646.                     /* we have entered the range */
  647.                     if (notcount-- == 0) {
  648.                         /* we just left it */
  649.                         dodraw = TRUE;
  650.                         inselection = FALSE;
  651.                         doinvert = FALSE;
  652.                     }
  653.                 }
  654.             }
  655.             thechar = *textp;
  656.             if ( ((thechar) < ATTR) || dodraw) {
  657.                 /* we hit a new attribute or selection range, draw a string now */
  658.                 
  659.                 if (linemod) {
  660.                     drawcount = textp - drawstart - blanks;
  661.                     if (drawcount > 0) {
  662. #ifdef SCRHILITE
  663.                         if (inselection)
  664.                             SETHILITE();
  665. #endif
  666.                         DrawText(invisible ? blankstart : drawstart, 0, drawcount);
  667.                         zapped = TRUE;
  668.                     }
  669.                     if (blanks) {
  670.                         /* only accumulate when line is cleared so we can skip */
  671.                         Move(blanks * emdp->fontwidth, 0);
  672.                         blanks = 0;
  673.                     }
  674.                     if (diacritics) {
  675.                         DrawText(blankstart, 0, diacritics);
  676.                         diacritics = 0;
  677.                     }
  678.                     drawstart = textp;
  679.                 }
  680.                 if (dodraw) {
  681.                     /* may be transiting selection range, set new mode & reset flag */
  682.                     dodraw = FALSE;
  683.                     if (!emdp->color)
  684.                         TextMode((textmode = (inselection ? notSrcCopy : srcCopy)));
  685.                 }
  686.                 if (thechar < ATTR) {
  687.                     /* hit a new attribute, put a blank down & switch font */
  688.                     if (linemod) {
  689. #ifdef SCRHILITE
  690.                         if (inselection)
  691.                             SETHILITE();
  692. #endif
  693.                         DrawChar(' ');
  694.                         drawstart++;
  695.                     }
  696.                     invisible = setscreenattr_qd(thechar);
  697.                 }
  698.             }
  699.             else if (!emdp->color && lineclr) {
  700.                 if (skiparr[*textp] && textmode == srcCopy) {
  701.                     /* add up consecutive blanks at right end */
  702.                     blanks++;
  703.                     continue;
  704.                 }
  705.                 else if (blanks > 2) {
  706.                     /* we'll break up line into smaller frags but will skip more
  707.                         spaces, an OK trade? */
  708.                     --textp;        /* back up to catch this char again */
  709.                     dodraw = TRUE;
  710.                     continue;
  711.                 }
  712.                 else
  713.                     blanks = 0;
  714.             }
  715.             diacritics += isdiacritic[thechar];
  716.         }
  717.         /* clean up any drawing needed for the rest of the line */
  718.         if (linemod && drawstart < lineend) {
  719.             /* make sure we draw even when attribute at end of line */
  720.             drawcount = textp - drawstart - blanks;
  721.             if (drawcount > 0) {
  722. #ifdef SCRHILITE
  723.                 if (inselection)
  724.                     SETHILITE();
  725. #endif
  726.                 DrawText(invisible ? blankstart : drawstart, 0, drawcount);
  727.                 zapped = TRUE;
  728.             }
  729.         }
  730.         blanks = 0;
  731.         if (diacritics) {
  732.             /* blank out stuff */
  733.             DrawText(blankstart, 0, diacritics);
  734.             diacritics = 0;
  735.         }
  736.         if (zapped) {
  737.             clrflg &= ~modmask[linecount];        /* reset clear flag */
  738.             zapped = FALSE;
  739.         }
  740.         yloc += emdp->lineheight;
  741.             /* fix for the next time around */
  742.     }
  743.     TextMode(srcCopy);
  744.     modflg = 0;
  745. }
  746.  
  747. /* resize the emulator screen and its textwindow */
  748.  
  749. setscreensize(fsize)
  750. int fsize;
  751. {
  752.  
  753.     int dv;
  754.     int dh;
  755.     int emv;                /* emulator height */
  756.     int emh;                /* emulator width */
  757.     short odsdraw = emdp->dsdraw;
  758.     
  759.     if (emdp->ibm_mode)
  760.         (*emdp->prepibmdraw)();
  761.     else
  762.         emprep();
  763.         
  764.     /*     .h   .v
  765.         480, 288 original 9 pt dimensions
  766.         560, 384 12 pt
  767.         640, 336 14 pt
  768.  
  769.         + 29, + 30 for controls & stuff
  770.     */
  771.     
  772.     setfontsize(fsize);
  773.     
  774.     emh = (emdp->lastcol + 1) * emdp->fontwidth + 2 * emdp->hoffset;
  775.     dh = emh + 29
  776.         - (((GrafPtr) emwindow)->portRect.right 
  777.             - ((GrafPtr) emwindow)->portRect.left); 
  778.     
  779.     emv = (emdp->lastrow + 1) * emdp->lineheight + emdp->voffset;
  780.     dv = emv + 30
  781.         - (((GrafPtr) emwindow)->portRect.bottom 
  782.             - ((GrafPtr) emwindow)->portRect.top); 
  783.     
  784.     prettyresize(dh, dv);
  785.     textwsize(emh + 28, emv + 12);                /* resize the text window */
  786.     SizeWindow(emwindow, emh + 29, emv + 30, (Boolean) FALSE);
  787.         
  788.     InvalRect(&((GrafPtr) emwindow)->portRect);
  789.     ClipRect(&((GrafPtr) emwindow)->portRect);
  790.  
  791.     if (windtightfit(emdp) || !indisplay(emwindow) ) {
  792.         /* if the window is not in the display, move if it necessary */
  793.         fitwindow(emdp);
  794.     }
  795.     setcontext(emdp);        /* reset globals before testds which may savecontext() */
  796.     testds(emdp);
  797.         /* useds() will be called if true */
  798.     
  799.     if (emdp->selrectset) {
  800.         /* resize selection rectangles */
  801.         selset(emdp->selystart, emdp->selxstart, emdp->selyend, emdp->selxend);
  802.         emdp->selrectvis = TRUE;
  803.             /* have update handler redraw */
  804.     }
  805.     newcurs(&emdp->cursrect);        /* reposition the cursor */
  806.     
  807.     if (emdp->ibm_mode) {
  808.         if (odsdraw)
  809.             endibmdraw_ds();
  810.         else
  811.             endibmdraw_qd();
  812.     }
  813.     else
  814.         emend();
  815.         
  816.     showcursor();
  817. }
  818.  
  819.  
  820. /* sets variables dependent upon font size */
  821.  
  822. setfontsize(fsize)
  823. int fsize;
  824. {
  825.     FontInfo fontinfo;                    /* font information */
  826.     
  827.     if (fsize == 9) {
  828.         emdp->hoffset = 0;
  829.         emdp->voffset = 0;
  830.     }
  831.     else if (fsize == 12) {
  832.         emdp->hoffset = 0;
  833.         emdp->voffset = 0;
  834.     }
  835.     else if (fsize == 14) {
  836.         emdp->hoffset = 6;
  837.         emdp->voffset = 0;
  838.     }
  839.     else if (fsize == 16) {
  840.         emdp->hoffset = 6;
  841.         emdp->voffset = 0;
  842.     }
  843.     else {
  844.         /* default to size 9 */
  845.         fsize = 9;
  846.         emdp->hoffset = 0;
  847.         emdp->voffset = 0;
  848.     }
  849.     TextSize(fsize);
  850.     emdp->fontsize = fsize;
  851.     
  852.     GetFontInfo(&fontinfo);
  853.     emdp->lineheight = fontinfo.ascent + fontinfo.descent + fontinfo.leading;
  854.     emdp->fontheight = fontinfo.ascent + fontinfo.descent;
  855.     emdp->fontdescent = fontinfo.descent + fontinfo.leading;
  856.  
  857.     emdp->fontwidth = CharWidth('m');
  858.         /* use the width of an em as the default width */
  859.  
  860.     /* these are offsets not relying on voffset */
  861.     emdp->curstop = emdp->lineheight - 1;
  862.     emdp->mrecttop = emdp->lineheight - 2 ;
  863.     
  864.     /* fix emdp->rightmarg, emdp->bigrect, & emdp->scrollrect for emulators */
  865.     
  866.     emdp->rightmarg = emdp->fontwidth * (emdp->lastcol + 1) + emdp->hoffset;
  867.     emdp->bottommarg = emdp->lineheight * emdp->linecount + emdp->voffset;
  868.  
  869.     emdp->bigrect.top = emdp->voffset;
  870.     emdp->bigrect.left = emdp->hoffset;
  871.     emdp->bigrect.bottom = emdp->bottommarg;
  872.     emdp->bigrect.right = emdp->rightmarg;
  873.  
  874.     emdp->scrollrect.top = emdp->scrolltop * emdp->lineheight  + emdp->voffset;
  875.     emdp->scrollrect.left = emdp->hoffset;
  876.     emdp->scrollrect.bottom = (emdp->scrollbottom + 1) * emdp->lineheight + emdp->voffset;
  877.     emdp->scrollrect.right = emdp->rightmarg;
  878.  
  879. }
  880.  
  881.  
  882.  
  883. /* handle a window update event in direct-screen drawing mode */
  884.  
  885. updatewind_ds() 
  886. {
  887.     RgnHandle tvisRgn;
  888.     Rect intersect;
  889.     GrafPtr oldport;
  890.     Rect wrect;
  891.     
  892.     if (emdp->backonly)
  893.         return;
  894.  
  895.     if (bkrd_act || !dsdrawok()) {
  896.         /* emdp->selrectvis || do a quickdraw update if in background */
  897.         updatewind_qd();
  898.         return;
  899.     }
  900.     if (!((WindowPeek) emwindow)->visible) {
  901.         return;
  902.     }
  903.  
  904.     GetPort(&oldport);
  905.     SetPort(emwindow);
  906.  
  907.     /* blank out cursors before drawing:  invert whole rect 
  908.         before setting cliprgn w/ beginupdate() */
  909.     if (emdp == keydp && trackon) {
  910.         InvertRect(&mouserect);
  911.     }
  912.     if (emdp->curson) {
  913.         InvertRect(&emdp->cursrect);
  914.     }
  915.  
  916.     emdp->mfwait = FALSE;
  917.  
  918.     BeginUpdate(emwindow);
  919.  
  920.     /* now when we invert again any portion in the update region will be inverted
  921.         to blank... */
  922.     /* we do prepibmdraw stuff again... */
  923.     prepibmdraw_ds();
  924.  
  925.     prettywind(TRUE);
  926.  
  927.     if (line25on(emdp)) {
  928.         line25refresh();
  929.     }
  930.     else {
  931.         if (emdp->termset) {
  932.             /* don't draw controls until there's a terminal selected */
  933.             if (emdp->controlschanged) {
  934.                 drawq1controls();
  935.                 copytoprect(emwindow);            /* try to copy the control pics to reuse */
  936.             }
  937.             else
  938.                 pastetoprect(emwindow);
  939.         }
  940.     }
  941.     drawversion("");
  942.     drawincount();
  943.     drawoutcount();
  944. /*
  945.     wrect = emdp->bigrect;
  946.     LocalToGlobal(&wrect.top);
  947.     LocalToGlobal(&wrect.bottom);
  948. */
  949.     if (SectRect(&emdp->bigrect, &(*emwindow->visRgn)->rgnBBox, &intersect)) {
  950.         /* update the em screen only if it needs it; thus
  951.             we can avoid undue screen glitching on minor update events... */
  952.         modflg = (long) SCRALLMOD;    /* set line-changed map to all TRUE */
  953.     }
  954.     if (modflg) {
  955.         if (emdp->selrectvis) {
  956.             /* if user has selected some text, invert it again within update clip
  957.                 before ds redraw; this results in poor performance... 
  958.                 reinvert update rgn, blank all, reinvert all */
  959.             selinvert(emdp);
  960.         }
  961.         if (!emdp->emdisable) {
  962.             /* update the emulator contents */
  963.             if (emdp->ibm_mode) {
  964.                 if (emdp->selrectvis || emdp->fontwidth == 8) {
  965.                     ibmdsbuf(scr_map, TRUE);
  966.                 }
  967.                 else {
  968.                     zapbuf(scr_map);
  969.                 }
  970.             }
  971.             else {
  972.                 emprep();
  973.                 emrefresh(emwindow, TRUE);
  974.                 emend();
  975.             }
  976.             modflg = 0;
  977.         }
  978.         if (emdp->ibm_keymode) {
  979.             arcrefresh();                    /* 3270ft bytes-transferred drawing */
  980.         }
  981.     }
  982.     
  983.     if (emdp->ibm_mode) {
  984.         status_info();
  985.     }
  986.     
  987.     emdp->event_reg &= ~SCREEN_EVENT;        /* the screen has been completely updated */
  988.  
  989.     EndUpdate(emwindow);            /* end the update */
  990.  
  991.     InvertRect(&emdp->cursrect);    /* turn the cursor on */
  992.     emdp->curson = TRUE;
  993.     setcursalarm();
  994.  
  995.     endibmdraw_ds();
  996.     SetPort(oldport);
  997. }
  998.  
  999.  
  1000. /*    new function to replace msg_out
  1001.  *    uses linear destination parameter rather than xpos, ypos to consolidate 
  1002.  *    arithmetic
  1003.  *
  1004.  *    write count bytes from srcptr to linear screen position dest 
  1005.  *    do not move cursor
  1006.  */
  1007.  
  1008. str_draw_ds(srcptr, count, attr)
  1009. unsigned char * srcptr;
  1010. register int count;
  1011. unsigned char attr;
  1012. {
  1013.     FONTS * oldfont;
  1014.     unsigned char thechar;
  1015.     int savex, savey;
  1016.     char invisible = FALSE;
  1017.     char invertdone = FALSE;
  1018.     Byte mmumode;
  1019.     
  1020.     if (updatewait()) {
  1021.         /* delay drawing */
  1022.         set_mod(srcptr, count);
  1023.         emdp->event_reg |= SCREEN_EVENT;
  1024.         return;
  1025.     }        
  1026.     if (bkrd_act || !dsdrawok()) {
  1027.         str_draw_qd(srcptr, count, attr);
  1028.         return;
  1029.     }
  1030.     else if (!((WindowPeek) emwindow)->visible)
  1031.         return;
  1032.         
  1033.  
  1034.     oldfont = thefont;
  1035.     savex = xpos;
  1036.     savey = ypos;
  1037.  
  1038.     ypos = (srcptr - scr_map) / emdp->linelength;
  1039.     xpos = (srcptr - (scr_map + (ypos * emdp->linelength)));
  1040.  
  1041.     prepibmdraw_ds();
  1042.     invisible = setscreenattr_ds(attr);
  1043.  
  1044.     count++;                /* set up for predecrement  */
  1045.     clrflg &= ~modmask[ypos];        /* reset clear flag */
  1046.     
  1047. #ifdef SWAPMMUMODE
  1048.     mmumode = true32b;            /* set MMU mode to 32 bits so high screen addresses OK */
  1049.     SwapMMUMode(&mmumode);        /* NB:  V-592:  "some Toolbox routines may not function" */
  1050. #endif
  1051.  
  1052.     while (--count > 0) 
  1053.     {
  1054.         if (invisible) {
  1055.             thechar = ' ';
  1056.             srcptr++;
  1057.         }
  1058.         else 
  1059.             thechar = *srcptr++;
  1060.         /* draw using an inverted font when within selection range */
  1061.         if (emdp->selrectvis) {
  1062.             if (zapinvert) {
  1063.                 if (!invertdone && !chkinvert()) {
  1064.                     /* we just left the selection range, reset the font */
  1065.                     setscreenattr_ds(attr);
  1066.                     invertdone = TRUE;
  1067.                     zapinvert = FALSE;
  1068.                 }
  1069.             }
  1070.             else {
  1071.                 if (chkinvert()) {
  1072.                     /* draw using an inverted font */
  1073.                     if (thefont == &boldfont)
  1074.                         thefont = &invboldfont;
  1075.                     else
  1076.                         thefont = &invfont;
  1077.                     zapinvert = TRUE;
  1078.                 }
  1079.                 else 
  1080.                     zapinvert = FALSE;
  1081.             }
  1082.         }
  1083.         zapchar(thechar);
  1084.  
  1085.         if (++xpos >= emdp->linelength) {
  1086.             xpos = 0;
  1087.             clrflg &= ~modmask[ypos];        /* reset clear flag */
  1088.             if (++ypos >= emdp->linecount)
  1089.                 ypos = 0;
  1090.         }
  1091.     }
  1092.  
  1093. #ifdef SWAPMMUMODE
  1094.     SwapMMUMode(&mmumode);    /* restore previous MMUMode */
  1095. #endif
  1096.  
  1097.     /* restore the old x, y values and the old cursor */
  1098.     xpos = savex;
  1099.     ypos = savey;
  1100.     thefont = oldfont;
  1101. }
  1102.  
  1103.  
  1104. /* draw a character on the screen; fix cursor later after cursor_ptr update */
  1105.  
  1106. ibmch_draw_ds(thechar, attr)
  1107. unsigned char thechar; 
  1108. unsigned char attr;
  1109. {
  1110.     FONTS * oldfont;
  1111.     Byte mmumode;
  1112.     
  1113.     if (updatewait()) {
  1114.         /* delay drawing */
  1115.         set_mod(cursor_ptr, 1);
  1116.         emdp->event_reg |= SCREEN_EVENT;
  1117.         return;
  1118.     }        
  1119.     if (bkrd_act || !dsdrawok()) {
  1120.         ibmch_draw_qd(thechar, attr);
  1121.         return;
  1122.     }
  1123.     else if (!((WindowPeek) emwindow)->visible)
  1124.         return;
  1125.         
  1126.     oldfont = thefont;
  1127.     if (setscreenattr_ds(attr))
  1128.         /* invisible */
  1129.         thechar = ' ';
  1130.         
  1131.     prepibmdraw_ds();
  1132.     
  1133.     if (chkinvert()) {
  1134.         /* draw using an inverted font for better appearance */
  1135.         if (thefont == &boldfont)
  1136.             thefont = &invboldfont;
  1137.         else
  1138.             thefont = &invfont;
  1139.         zapinvert = TRUE;
  1140.     }
  1141.     else
  1142.         zapinvert = FALSE;
  1143.  
  1144. #ifdef SWAPMMUMODE
  1145.     mmumode = true32b;            /* set MMU mode to 32 bits so high addresses OK */
  1146.     SwapMMUMode(&mmumode);        /* NB:  V-592:  "some Toolbox routines may not function" */
  1147. #endif
  1148.  
  1149.     zapchar(thechar);
  1150.     clrflg &= ~modmask[ypos];        /* reset clear flag */
  1151.     
  1152. #ifdef SWAPMMUMODE
  1153.     SwapMMUMode(&mmumode);
  1154. #endif
  1155.  
  1156.     endibmdraw_ds();
  1157.     thefont = oldfont;
  1158. }
  1159.  
  1160.  
  1161.  
  1162. screen_upd_ds()
  1163. {
  1164.     if (updatewait())
  1165.         return;
  1166.         
  1167.     if (bkrd_act || !dsdrawok()) {
  1168.         /* emdp->selrectvis was also a case ... */
  1169.         screen_upd_qd();
  1170.         return;
  1171.     }
  1172.     else if (!((WindowPeek) emwindow)->visible)
  1173.         return;
  1174.         
  1175.     emdp->event_reg &= ~SCREEN_EVENT;
  1176. #ifdef BITSELDRAW
  1177.     if (emdp->selrectvis) {
  1178.         /* if user has selected some text, we must clear and rehighlight later */
  1179.         selclear(emdp);
  1180.         emdp->selrectvis = FALSE;
  1181.         tm_tset(12, selrestore, emdp, emdp->sel_tm);
  1182.     }
  1183. #endif
  1184.     if (emdp->ibm_mode) {
  1185.         prepibmdraw_ds();
  1186.         if (emdp->selrectvis || emdp->fontwidth == 8) {
  1187.             /* do a zapchar deal like emrefresh... */
  1188.             ibmdsbuf(scr_map, TRUE);
  1189.         }
  1190.         else {
  1191.             /* TODO may have wrong font because attr not set! */
  1192.             zapbuf(scr_map);
  1193.         }
  1194.         endibmdraw_ds();
  1195.     }
  1196.     else {
  1197.         short hadcursor;
  1198.         
  1199.         hadcursor = emdp->curson;
  1200.         
  1201.         emprep();
  1202.         emrefresh(emwindow, TRUE);
  1203.         emend();
  1204.  
  1205.         if (hadcursor) {
  1206.             /* if the cursor was visible, make sure it stays that way */
  1207.             InvertRect(&emdp->cursrect);    /* turn the cursor on */
  1208.             emdp->curson = TRUE;
  1209.             setcursalarm();
  1210.         }
  1211.     }
  1212. }
  1213.  
  1214.  
  1215. /*
  1216. *****  quick clear the first 24 lines off the screen
  1217. */
  1218.  
  1219. clear_scr_ds()
  1220. {
  1221.     if (updatewait()) {
  1222.         modflg = SCRALLMOD;
  1223.         emdp->event_reg |= SCREEN_EVENT;
  1224.         return;
  1225.     }
  1226.         
  1227.     if (clrflg >= SCRALLMOD)
  1228.         /* screen is already clear */
  1229.         return;
  1230.  
  1231.     if (mousecurson) {
  1232.         HideCursor();
  1233.         mousecurson = FALSE;
  1234.     }
  1235.  
  1236.     emdp->bigrect.top = emdp->voffset;
  1237.     EraseRect(&emdp->bigrect);
  1238.     if (emdp->selrectvis) {
  1239.         /* if user has selected some text, we must rehighlight */
  1240.         if (updatewait()) {
  1241.             emdp->selrectvis = FALSE;
  1242.             tm_tset(2, selrestore, emdp, emdp->sel_tm);
  1243.         }
  1244.         else
  1245.             selinvert(emdp);
  1246.     }
  1247.     emdp->curson = FALSE;
  1248.  
  1249.     clrflg = SCRALLMOD;
  1250.     if (emdp == keydp)
  1251.         trackon = FALSE;
  1252.  
  1253. }
  1254.  
  1255. prepibmdraw_ds()
  1256. {
  1257.     if (mousecurson) {
  1258.         ShieldCursor(&emdp->zaprect, 0L);
  1259.             /* 0L equivalent to pass(Point(0,0)) */
  1260.         /* HideCursor(); */
  1261.         mousecurson = FALSE;
  1262.     }
  1263.     if (emdp->curson) {
  1264.         /* if cursor visible, invert it */
  1265.         InvertRect(&emdp->cursrect);
  1266.         emdp->curson = FALSE;
  1267.     }
  1268.     if (emdp == keydp && trackon) {
  1269.         /* if mouserect visible, invert it */
  1270.         InvertRect(&mouserect);
  1271.         trackon = FALSE;
  1272.     }
  1273.     zapuline = FALSE;
  1274.     zapinvert = FALSE;
  1275. }
  1276.  
  1277.  
  1278. endibmdraw_ds()
  1279. {
  1280.     if (!mousecurson) {
  1281.         /* if (!mfbackground)
  1282.             ObscureCursor();                hide until next motion */
  1283.         ShowCursor();
  1284.         mousecurson = TRUE;
  1285.     }
  1286. }
  1287.  
  1288.  
  1289. /* are we in the selection range and do need to invert 
  1290.     the character we just drew? */
  1291.         
  1292. chkinvert() 
  1293. {
  1294.     int fixinv;
  1295.  
  1296.     fixinv = FALSE;
  1297.     if (emdp->selrectvis) {
  1298.         if (ypos == emdp->selystart && ypos == emdp->selyend) {
  1299.             /* on a single line */
  1300.             if (xpos >= emdp->selxstart && xpos < emdp->selxend)
  1301.                 fixinv = TRUE;
  1302.         }
  1303.         else if (ypos == emdp->selystart) {
  1304.             /* might be in selection */
  1305.             if (xpos >= emdp->selxstart)
  1306.                 fixinv = TRUE;
  1307.         }
  1308.         else if (ypos == emdp->selyend) {
  1309.             /* might be in selection */
  1310.             if (xpos < emdp->selxend)
  1311.                 fixinv = TRUE;
  1312.         }
  1313.         else if (ypos > emdp->selystart && ypos < emdp->selyend) {
  1314.             /* definitely in selection */
  1315.             fixinv = TRUE;
  1316.         }
  1317.     }
  1318. #ifdef ZANY
  1319.     /* removed to fix vt100... */
  1320.     if (fixinv)
  1321.         zapinvert = TRUE;
  1322.     else
  1323.         zapinvert = FALSE;
  1324. #endif
  1325.     return(fixinv);
  1326. }
  1327.  
  1328.  
  1329. /*    redraws the characters on the screen from a screen buffer.
  1330.     Due to the line leading, window updates need to have the inversion
  1331.     of the selection range done on the whole range--inverted char drawing
  1332.     would leave non-inverted bit rows.
  1333.     
  1334.     ibmdsbuf specializes in drawing an update with a selection range
  1335. */
  1336.  
  1337. ibmdsbuf(scrbuf, doinvert)
  1338. unsigned char * scrbuf;
  1339. short doinvert;
  1340. {
  1341.     register unsigned char * textp; 
  1342.     register unsigned char * lineend;
  1343.     register unsigned long linemod;
  1344.     register int notstart;                /* start of selection range */
  1345.     register int notcount;                /* count of selection range */
  1346.     register unsigned char thechar;
  1347.     register int dodraw;                    /* draw triggered by entering selection range */
  1348.     register unsigned long lineclr;
  1349.  
  1350.     unsigned char * attp;
  1351.     unsigned char attr;
  1352.     int invisible;                /* we're in an invisible field */
  1353.     FONTS * oldfont;
  1354.     int savex = xpos;
  1355.     int savey = ypos;
  1356.     char zapped = FALSE;
  1357.     Byte mmumode;
  1358.     
  1359.     textp = scrbuf;
  1360.     xpos = 0;
  1361.     
  1362.     invisible = FALSE;
  1363.     
  1364.     /* find and set current attribute */
  1365.     if (*scrbuf < ATTR)
  1366.         thechar = *scrbuf;
  1367.     else {
  1368.         attp = look_attr(scrbuf, BACK);
  1369.         attr = *attp;
  1370.     }
  1371.     dodraw = TRUE;        /* force attr selection first time through */
  1372.     oldfont = thefont;
  1373.     if (doinvert) {
  1374.         if (emdp->selrectvis) {
  1375.             /* calculate character range over which we use notSrcCopy */
  1376.             notstart = emdp->selystart * emdp->linelength + emdp->selxstart;
  1377.             notcount = emdp->selyend * emdp->linelength + emdp->selxend - notstart;
  1378.             if (notcount == 0)
  1379.                 doinvert = FALSE;
  1380.         }
  1381.         else 
  1382.             doinvert = FALSE;
  1383.     }
  1384. #ifdef CLEARONALLMOD
  1385.     if (modflg == SCRALLMOD) {
  1386.         /* screen was completely modified, clearing will speed blanks */
  1387.         clear_scr_ds();
  1388.     }
  1389. #endif
  1390.         
  1391. #ifdef SWAPMMUMODE
  1392.     mmumode = true32b;            /* set MMU mode to 32 bits so high addresses OK */
  1393.     SwapMMUMode(&mmumode);        /* NB:  V-592:  "some Toolbox routines may not function" */
  1394. #endif
  1395.  
  1396.     lineend = textp + emdp->linelength;
  1397.     for (ypos = 0; ypos <= emdp->lastrow; ypos++, lineend += emdp->linelength) {
  1398.         linemod = modflg & modmask[ypos];
  1399.         lineclr = clrflg & modmask[ypos];
  1400.         
  1401.         for ( ; textp < lineend; textp++, xpos++) {
  1402.             thechar = *textp;
  1403.             if (doinvert) {
  1404.                 /* check to see if we're in the selection range */
  1405.                 if (notstart-- == 0) {
  1406.                     /* we just entered the range */
  1407.                     dodraw = TRUE;
  1408.                     zapinvert = TRUE;
  1409.                 }
  1410.                 if (notstart < 0) {
  1411.                     /* we have entered the range */
  1412.                     if (notcount-- == 0) {
  1413.                         /* we just left it */
  1414.                         dodraw = TRUE;
  1415.                         zapinvert = FALSE;
  1416.                         doinvert = FALSE;
  1417.                     }
  1418.                 }
  1419.             }
  1420.             if (thechar < ATTR) {
  1421.                 attr = thechar;
  1422.                 dodraw = TRUE;
  1423.             }
  1424.             if (dodraw) {
  1425.                 /* hit a new attribute, put a blank down & switch font */
  1426.                 dodraw = FALSE;
  1427.                 switch (attr & DSPD) {
  1428.                     case 0:
  1429.                         /* normal, not selector-pen detectable */
  1430.                     case 4: {
  1431.                         /* normal, selector-pen detectable */
  1432.                         thefont = (zapinvert ? &invfont : &font);
  1433.                         invisible = FALSE;
  1434.                         break;
  1435.                     }
  1436.                     case 8: {
  1437.                         /* intense */
  1438.                         thefont = (zapinvert ? &invboldfont : &boldfont);
  1439.                         invisible = FALSE;
  1440.                         break;
  1441.                     }
  1442.                     case 12: {
  1443.                         /* invisible */
  1444.                         invisible = TRUE;
  1445.                         break;
  1446.                     }
  1447.                 }
  1448.                 if (thechar < ATTR)
  1449.                     /* make sure it was an attribute that triggered drawing */
  1450.                     thechar = ' ';
  1451.             }
  1452.             if (linemod) {
  1453.                 if (lineclr && !zapinvert && skiparr[thechar]) {
  1454.                     /* we don't need to draw blanks */
  1455.                     continue;
  1456.                 }
  1457.                 if (invisible) {
  1458.                     thechar = ' ';
  1459.                 }
  1460.                 zapchar(thechar);
  1461.                 zapped = TRUE;
  1462.             }
  1463.         }
  1464.         if (zapped) {
  1465.             clrflg &= ~modmask[ypos];        /* reset cleared flag */
  1466.             zapped = FALSE;
  1467.         }
  1468.         xpos = 0;
  1469.     }
  1470. #ifdef SWAPMMUMODE
  1471.     SwapMMUMode(&mmumode);
  1472. #endif
  1473.  
  1474.     xpos = savex;
  1475.     ypos = savey;
  1476.     thefont = oldfont;
  1477.     zapinvert = FALSE;
  1478.     modflg = 0;
  1479. }
  1480.  
  1481.  
  1482. /* cursor handling routines for both drawing styles */
  1483.  
  1484. /*    fix the rect arg to make a proper cursor at the current location 
  1485.  *    of cursor_ptr 
  1486.  */
  1487.  
  1488. ibmnewcurs(thecursor)
  1489. Rect * thecursor;
  1490. {
  1491.  
  1492.     ypos = (cursor_ptr - scr_map) / emdp->linelength;
  1493.     xpos = (cursor_ptr - (scr_map + (ypos * emdp->linelength)));
  1494.  
  1495.     newcurs(thecursor);
  1496. }
  1497.  
  1498.  
  1499. /* recalculate cursor rectangle and see if we can draw it */
  1500.  
  1501. setibmcursor()
  1502. {
  1503.     if ((!mfbackground && bkrd_act) || updatewait()) {
  1504.         /* don't invert cursor while in background */
  1505.         ypos = (cursor_ptr - scr_map) / emdp->linelength;
  1506.         xpos = (cursor_ptr - (scr_map + (ypos * emdp->linelength)));
  1507.         emdp->cursorwait = TRUE;
  1508.         return();
  1509.     }
  1510.     if (emdp->curson) {
  1511.         /* turn off old cursor */
  1512.         InvertRect(&emdp->cursrect);
  1513.     }
  1514.     ibmnewcurs(&emdp->cursrect);
  1515.     InvertRect(&emdp->cursrect);
  1516.     emdp->curson = TRUE;
  1517.     setcursalarm();
  1518. }
  1519.  
  1520.  
  1521. /* set new cursor but don't draw it yet */
  1522.  
  1523. newibmcursor()
  1524. {
  1525.     if ((!mfbackground && bkrd_act) || updatewait()) {
  1526.         /* don't invert cursor while in background */
  1527.         ypos = (cursor_ptr - scr_map) / emdp->linelength;
  1528.         xpos = (cursor_ptr - (scr_map + (ypos * emdp->linelength)));
  1529.         emdp->cursorwait = TRUE;
  1530.         return();
  1531.     }
  1532.     if (emdp->curson) {
  1533.         InvertRect(&emdp->cursrect);
  1534.         emdp->curson = FALSE;
  1535.     }
  1536.     ibmnewcurs(&emdp->cursrect);
  1537. }
  1538.  
  1539.  
  1540. /* called to refresh IBM keyboard lights */
  1541.  
  1542. status_info()
  1543. {
  1544.     /* called when screen needs to be updated */
  1545.     
  1546.     if (emdp->event_reg & SYS_LOCK)
  1547.         showsyslock();
  1548.  
  1549.     if (emdp->event_reg & KYBD_LOCK)
  1550.         showkbdlock();
  1551. }
  1552.  
  1553.  
  1554. clrstatus_info()
  1555. {
  1556.     /* called when screen needs to be updated */
  1557.     
  1558.     if (emdp->event_reg & SYS_LOCK)
  1559.         clrsyslock();
  1560.  
  1561.     if (emdp->event_reg & KYBD_LOCK)
  1562.         clrkbdlock();
  1563. }
  1564.  
  1565.  
  1566. /*    Cause the cursor to blink if blinking is on;
  1567.     Also turns Macintosh cursor back on if it has been hidden.
  1568. */
  1569.  
  1570. cursorblink()
  1571. {
  1572.     if (!mousecurson) {
  1573.         showcursor();
  1574.     }
  1575.     /* do nothing if an update is pending, in background, or terminal
  1576.         type not yet selected */
  1577.     if ((!mfbackground && bkrd_act) || updatewait()) {
  1578.         /* ^ implies the q3labels are up, DON'T invert the cursor */
  1579.          return;
  1580.     }
  1581.  
  1582.     if (emdp->cursorwait) {
  1583.         /* update the cursor so it's in the current position */
  1584.         emdp->cursorwait = FALSE;
  1585.         if (emdp->ibm_mode)
  1586.             setibmcursor();
  1587.         else
  1588.             setcursor();
  1589.     }
  1590.     else {    
  1591.         if (emdp->changecurs) {
  1592.             /* we assume we are only called every blink time */
  1593.             if (emdp->curson) {
  1594.                 if (!bkrd_act && emdp->connopen) {
  1595.                     /* it's now off if we're not in the background 
  1596.                         and have a connection */
  1597.                     emdp->curson = FALSE;
  1598.                     InvertRect(&emdp->cursrect);
  1599.                 }
  1600.             }
  1601.             else {
  1602.                 /* turn it on */
  1603.                 emdp->curson = TRUE;
  1604.                 InvertRect(&emdp->cursrect);
  1605.             }
  1606.         }
  1607.         else if (emdp->curson == FALSE) {
  1608.             emdp->curson = TRUE;
  1609.             InvertRect(&emdp->cursrect);
  1610.         }
  1611.     }
  1612. }
  1613.  
  1614.  
  1615. /* set QuickDraw drawing state to correspond to current attribute */
  1616.  
  1617. setscreenattr_qd(attr)
  1618. unsigned char attr;
  1619. {
  1620.     int invisible = FALSE;
  1621.     int protected = 0;
  1622.     int field = ATNORM;
  1623.     
  1624.     if (emdp->color && (attr & PROT)) {
  1625.         /* protected fields show up in color */
  1626.         protected = ATPROT;
  1627.     }
  1628.     switch (attr & DSPD) {
  1629.         case 0: {
  1630.             /* normal, not selector-pen detectable */
  1631.             TextFont(emdp->normfont);
  1632.             field = ATNORM;
  1633.             break;
  1634.         }
  1635.         case 4: {
  1636.             /* normal, selector-pen detectable */
  1637.             TextFont(emdp->normfont);
  1638.             field = ATSENSE;
  1639.             break;
  1640.         }
  1641.         case 8: {
  1642.             /* intense */
  1643.             TextFont(emdp->highfont);
  1644.             field = ATINTENSE;
  1645.             break;
  1646.         }
  1647.         case 12: {
  1648.             /* invisible */
  1649.             TextFont(emdp->normfont);
  1650.             field = ATINVIS;
  1651.             invisible = TRUE;
  1652.             break;
  1653.         }
  1654.     }
  1655.     if (emdp->color) {
  1656.         RGBForeColor(&emdp->colormap.colors[field + protected]);
  1657.         RGBBackColor(&emdp->colormap.colors[field + protected + ATBACK]);
  1658.     }
  1659.     return(invisible);
  1660. }
  1661.  
  1662.  
  1663.  
  1664. setscreenattr_ds(attr)
  1665. unsigned char attr;
  1666. {
  1667.     int invisible = FALSE;
  1668.     
  1669.     switch (attr & DSPD) {
  1670.         case 0:
  1671.             /* normal, not selector-pen detectable */
  1672.         case 4: {
  1673.             /* normal, selector-pen detectable */
  1674.             thefont = &font;
  1675.             break;
  1676.         }
  1677.         case 8: {
  1678.             /* intense */
  1679.             thefont = &boldfont;
  1680.             break;
  1681.         }
  1682.         case 12: {
  1683.             /* invisible */
  1684.             invisible = TRUE;
  1685.             break;
  1686.         }
  1687.     }
  1688.     return(invisible);
  1689. }
  1690.  
  1691. /* was a useful code fragment */
  1692. #ifdef CHARINVERT
  1693.     if (chkinvert()) {
  1694.         chinvrect.top = ypos * emdp->lineheight + 2;                /* top 2 skipped by zap */
  1695.         chinvrect.left = xpos * emdp->fontwidth;
  1696.         chinvrect.bottom = chinvrect.top + emdp->fontheight - 2;    /* - 2 skipped by zap */
  1697.         chinvrect.right = chinvrect.left + emdp->fontwidth;
  1698.         
  1699.         InvertRect(&chinvrect);
  1700.     }
  1701. #endif
  1702.  
  1703.  
  1704. /* set vectors to employ the direct-to-screen drawing routines 
  1705.     and reset important variables 
  1706. */
  1707.  
  1708. useds(twp)
  1709. struct winds * twp;
  1710. {
  1711.     extern int scrollup_ds();
  1712.     
  1713.     twp->dsdraw = TRUE;
  1714.  
  1715.     /* generic */
  1716.     twp->screen_upd = screen_upd_ds;
  1717.     twp->updatewind = updatewind_ds;
  1718.  
  1719.     /* IBM specific */
  1720.     twp->prepibmdraw = prepibmdraw_ds;
  1721.     twp->ch_draw = ibmch_draw_ds;
  1722.     twp->str_draw = str_draw_ds;
  1723.     twp->clear_scr = clear_scr_ds;
  1724.  
  1725.     /* ASCII */
  1726.     twp->scrollup = scrollup_ds;
  1727.  
  1728.     if (buildfonts(twp) || setlinestarts(twp))
  1729.         useqd(twp);
  1730.  
  1731.     setshield(twp);
  1732.     
  1733. }
  1734.  
  1735.  
  1736. /* set drawing routine pointers to point to quickdraw routines */
  1737.  
  1738. useqd(twp)
  1739. struct winds * twp;
  1740. {
  1741.     extern int scrollup_qd();
  1742.  
  1743.     twp->dsdraw = FALSE;
  1744.  
  1745.     /* generic */
  1746.     twp->updatewind = updatewind_qd;
  1747.     twp->screen_upd = screen_upd_qd;
  1748.  
  1749.     /* IBM specific */
  1750.     twp->prepibmdraw = prepibmdraw_qd;
  1751.     twp->ch_draw = ibmch_draw_qd;
  1752.     twp->str_draw = str_draw_qd;
  1753.     twp->clear_scr = clear_scr_qd;
  1754.  
  1755.     /* ASCII */
  1756.     twp->scrollup = scrollup_qd;
  1757. }
  1758.  
  1759.  
  1760. /*    
  1761.     Check to see if the visRgn is large enough (i.e. no windows in front of this
  1762.     one) so we can use direct to screen drawing; return TRUE if so. 
  1763.     
  1764.     Replaces FrontWindow() test so multiple windows can run fast.
  1765. */
  1766.  
  1767. dsdrawok()
  1768. {
  1769.     RgnPtr visrgn;
  1770.     
  1771.     if (!riskydsdraw) {
  1772.         if (emwindow == FrontWindow()) {
  1773.             return(TRUE);
  1774.         }
  1775.     }
  1776.     else {
  1777.         /* use the slightly unreliable visRgn, which doesn't always
  1778.             get updated quickly enough */
  1779.         visrgn = *((GrafPtr) emwindow)->visRgn;
  1780.         if (visrgn->rgnSize == 10) {
  1781.             /* the visible region is a rectangle */
  1782.             if ( (visrgn->rgnBBox.top <= emdp->bigrect.top)
  1783.                 && (visrgn->rgnBBox.left <= emdp->bigrect.left)
  1784.                 && (visrgn->rgnBBox.bottom >= emdp->bigrect.bottom)
  1785.                 && (visrgn->rgnBBox.right >= emdp->bigrect.right)
  1786.             )
  1787.                 /* and the region box encloses the bigrect display
  1788.                     rectangle, so we can use direct to screen algorithm */
  1789.                 return(TRUE);
  1790.         }    
  1791.     }
  1792.     return(FALSE);
  1793. }
  1794.  
  1795.  
  1796.  
  1797. showcursor()
  1798. {
  1799.     if (!mousecurson) {
  1800.         ShowCursor();
  1801.         mousecurson = TRUE;
  1802.     }
  1803. }
  1804.  
  1805.  
  1806. /* some general screen routines */
  1807.  
  1808. /*    fix the rect arg to make a proper cursor at the current location 
  1809.  *    of cursor_ptr 
  1810.  */
  1811.  
  1812. newcurs(thecursor)
  1813. Rect * thecursor;
  1814. {
  1815.     if (emdp->blockcurs) {
  1816.         thecursor->top = ypos * emdp->lineheight + 1 + emdp->voffset;
  1817.         thecursor->left = xpos * fontwidth + emdp->hoffset;
  1818.         thecursor->bottom = thecursor->top - 1 + emdp->lineheight;
  1819.         thecursor->right = thecursor->left + fontwidth;
  1820.     }
  1821.     else {
  1822.         thecursor->top = ypos * emdp->lineheight + emdp->curstop + emdp->voffset;
  1823.         thecursor->left = xpos * fontwidth + emdp->hoffset;
  1824.         thecursor->bottom = thecursor->top + 1;
  1825.         thecursor->right = thecursor->left + fontwidth;
  1826.     }
  1827. }
  1828.  
  1829.  
  1830. /* position a new cursor and draw it */
  1831.  
  1832. setcursor()
  1833. {
  1834.     if (emwindow == NULL)
  1835.         return;
  1836.         
  1837.     if ((!mfbackground && bkrd_act) || updatewait()) {
  1838.         /* don't invert cursor while in background () */
  1839.         emdp->cursorwait = TRUE;
  1840.         return;
  1841.     }
  1842.     if (emdp->curson) {
  1843.         /* turn off old cursor */
  1844.         InvertRect(&emdp->cursrect);
  1845.     }
  1846.     newcurs(&emdp->cursrect);
  1847.  
  1848.     InvertRect(&emdp->cursrect);
  1849.     emdp->curson = TRUE;
  1850.     setcursalarm();
  1851. }
  1852.  
  1853.  
  1854. /* position a new cursor without drawing it */
  1855.  
  1856. newcursor()
  1857. {
  1858.     if (emwindow == NULL)
  1859.         return;
  1860.         
  1861.     if ((!mfbackground && bkrd_act) || updatewait()) {
  1862.         /* don't invert cursor while in q3label background  */
  1863.         emdp->cursorwait = TRUE;
  1864.         return;
  1865.     }
  1866.     if (emdp->curson) {
  1867.         InvertRect(&emdp->cursrect);
  1868.         emdp->curson = FALSE;
  1869.     }
  1870.     newcurs(&emdp->cursrect);
  1871. }
  1872.  
  1873.  
  1874. /* set the cursor to be turned on at the correct time */
  1875.  
  1876. setcursalarm()
  1877. {
  1878.     cursalarm = cticks + ((paramptr->volClick & 0x0f) << 2);
  1879.         /* set count between blinks to user parameter setting */
  1880. }
  1881.  
  1882.  
  1883. /* CURSOR support */
  1884.  
  1885. emcursopen()
  1886. {
  1887.     emdp->changecurs = TRUE;
  1888. }
  1889.  
  1890.  
  1891. emcursclose()
  1892. {
  1893.     emdp->changecurs = FALSE;
  1894. }
  1895.  
  1896.  
  1897. /* timer upcall to restore the selection after it has been erased */
  1898.  
  1899. selrestore(twp)
  1900. struct winds * twp;
  1901. {
  1902.     GrafPtr savegraf;
  1903.     
  1904.     if (twp->emwindow == NULL)
  1905.         return;
  1906.         
  1907.     if (updatewait() || twp->modflg) {
  1908.         /* arrange to be called back while waiting for update */
  1909.         tm_tset(2, selrestore, twp, twp->sel_tm);
  1910.         return;
  1911.     }
  1912.     GetPort(&savegraf);
  1913.     SetPort(twp->emwindow);
  1914.     /* re-highlight selection */
  1915.     
  1916.     selinvert(twp);
  1917.     twp->selrectvis = TRUE;
  1918.     SetPort(savegraf);
  1919. }
  1920.  
  1921.  
  1922.  
  1923.